using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using log4net;
using Triton.Common;
using Triton.Common.LogUtilities;
using Triton.Game;

namespace Triton.Bot
{
	public static class RoutineManager
	{
		public delegate void RoutineEvent(IRoutine routine);

		private static readonly ILog ilog_0 = Logger.GetLoggerInstanceForType();

		[CompilerGenerated]
		private static List<IRoutine> list_0;

		[CompilerGenerated]
		private static RoutineEvent routineEvent_0;

		[CompilerGenerated]
		private static RoutineEvent routineEvent_1;

		[CompilerGenerated]
		private static RoutineEvent routineEvent_2;

		[CompilerGenerated]
		private static RoutineEvent routineEvent_3;

		[CompilerGenerated]
		private static RoutineEvent routineEvent_4;

		[CompilerGenerated]
		private static RoutineEvent routineEvent_5;

		private static IRoutine iroutine_0;

		[CompilerGenerated]
		private static EventHandler<RoutineChangedEventArgs> eventHandler_0;

		public static List<IRoutine> Routines
		{
			[CompilerGenerated]
			get
			{
				return list_0;
			}
			[CompilerGenerated]
			private set
			{
				list_0 = value;
			}
		}

		private static string String_0 => Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);

		public static string RoutinesPath => Path.Combine(String_0, "Routines");

		public static IRoutine CurrentRoutine
		{
			get
			{
				return iroutine_0;
			}
			set
			{
				if (BotManager.IsRunning)
				{
					throw new InvalidOperationException("The CurrentRoutine cannot change while the bot is running. Please Stop it first.");
				}
				if (value == null)
				{
					throw new InvalidOperationException("The CurrentRoutine cannot be set to null.");
				}
				if (iroutine_0 != value)
				{
					IRoutine old = iroutine_0;
					iroutine_0 = value;
					TritonHs.InvokeEvent(eventHandler_0, null, new RoutineChangedEventArgs(old, iroutine_0));
				}
			}
		}

		public static event RoutineEvent PreStart
		{
			[CompilerGenerated]
			add
			{
				RoutineEvent routineEvent = routineEvent_0;
				RoutineEvent routineEvent2;
				do
				{
					routineEvent2 = routineEvent;
					RoutineEvent value2 = (RoutineEvent)Delegate.Combine(routineEvent2, value);
					routineEvent = Interlocked.CompareExchange(ref routineEvent_0, value2, routineEvent2);
				}
				while ((object)routineEvent != routineEvent2);
			}
			[CompilerGenerated]
			remove
			{
				RoutineEvent routineEvent = routineEvent_0;
				RoutineEvent routineEvent2;
				do
				{
					routineEvent2 = routineEvent;
					RoutineEvent value2 = (RoutineEvent)Delegate.Remove(routineEvent2, value);
					routineEvent = Interlocked.CompareExchange(ref routineEvent_0, value2, routineEvent2);
				}
				while ((object)routineEvent != routineEvent2);
			}
		}

		public static event RoutineEvent PostStart
		{
			[CompilerGenerated]
			add
			{
				RoutineEvent routineEvent = routineEvent_1;
				RoutineEvent routineEvent2;
				do
				{
					routineEvent2 = routineEvent;
					RoutineEvent value2 = (RoutineEvent)Delegate.Combine(routineEvent2, value);
					routineEvent = Interlocked.CompareExchange(ref routineEvent_1, value2, routineEvent2);
				}
				while ((object)routineEvent != routineEvent2);
			}
			[CompilerGenerated]
			remove
			{
				RoutineEvent routineEvent = routineEvent_1;
				RoutineEvent routineEvent2;
				do
				{
					routineEvent2 = routineEvent;
					RoutineEvent value2 = (RoutineEvent)Delegate.Remove(routineEvent2, value);
					routineEvent = Interlocked.CompareExchange(ref routineEvent_1, value2, routineEvent2);
				}
				while ((object)routineEvent != routineEvent2);
			}
		}

		public static event RoutineEvent PreTick
		{
			[CompilerGenerated]
			add
			{
				RoutineEvent routineEvent = routineEvent_2;
				RoutineEvent routineEvent2;
				do
				{
					routineEvent2 = routineEvent;
					RoutineEvent value2 = (RoutineEvent)Delegate.Combine(routineEvent2, value);
					routineEvent = Interlocked.CompareExchange(ref routineEvent_2, value2, routineEvent2);
				}
				while ((object)routineEvent != routineEvent2);
			}
			[CompilerGenerated]
			remove
			{
				RoutineEvent routineEvent = routineEvent_2;
				RoutineEvent routineEvent2;
				do
				{
					routineEvent2 = routineEvent;
					RoutineEvent value2 = (RoutineEvent)Delegate.Remove(routineEvent2, value);
					routineEvent = Interlocked.CompareExchange(ref routineEvent_2, value2, routineEvent2);
				}
				while ((object)routineEvent != routineEvent2);
			}
		}

		public static event RoutineEvent PostTick
		{
			[CompilerGenerated]
			add
			{
				RoutineEvent routineEvent = routineEvent_3;
				RoutineEvent routineEvent2;
				do
				{
					routineEvent2 = routineEvent;
					RoutineEvent value2 = (RoutineEvent)Delegate.Combine(routineEvent2, value);
					routineEvent = Interlocked.CompareExchange(ref routineEvent_3, value2, routineEvent2);
				}
				while ((object)routineEvent != routineEvent2);
			}
			[CompilerGenerated]
			remove
			{
				RoutineEvent routineEvent = routineEvent_3;
				RoutineEvent routineEvent2;
				do
				{
					routineEvent2 = routineEvent;
					RoutineEvent value2 = (RoutineEvent)Delegate.Remove(routineEvent2, value);
					routineEvent = Interlocked.CompareExchange(ref routineEvent_3, value2, routineEvent2);
				}
				while ((object)routineEvent != routineEvent2);
			}
		}

		public static event RoutineEvent PreStop
		{
			[CompilerGenerated]
			add
			{
				RoutineEvent routineEvent = routineEvent_4;
				RoutineEvent routineEvent2;
				do
				{
					routineEvent2 = routineEvent;
					RoutineEvent value2 = (RoutineEvent)Delegate.Combine(routineEvent2, value);
					routineEvent = Interlocked.CompareExchange(ref routineEvent_4, value2, routineEvent2);
				}
				while ((object)routineEvent != routineEvent2);
			}
			[CompilerGenerated]
			remove
			{
				RoutineEvent routineEvent = routineEvent_4;
				RoutineEvent routineEvent2;
				do
				{
					routineEvent2 = routineEvent;
					RoutineEvent value2 = (RoutineEvent)Delegate.Remove(routineEvent2, value);
					routineEvent = Interlocked.CompareExchange(ref routineEvent_4, value2, routineEvent2);
				}
				while ((object)routineEvent != routineEvent2);
			}
		}

		public static event RoutineEvent PostStop
		{
			[CompilerGenerated]
			add
			{
				RoutineEvent routineEvent = routineEvent_5;
				RoutineEvent routineEvent2;
				do
				{
					routineEvent2 = routineEvent;
					RoutineEvent value2 = (RoutineEvent)Delegate.Combine(routineEvent2, value);
					routineEvent = Interlocked.CompareExchange(ref routineEvent_5, value2, routineEvent2);
				}
				while ((object)routineEvent != routineEvent2);
			}
			[CompilerGenerated]
			remove
			{
				RoutineEvent routineEvent = routineEvent_5;
				RoutineEvent routineEvent2;
				do
				{
					routineEvent2 = routineEvent;
					RoutineEvent value2 = (RoutineEvent)Delegate.Remove(routineEvent2, value);
					routineEvent = Interlocked.CompareExchange(ref routineEvent_5, value2, routineEvent2);
				}
				while ((object)routineEvent != routineEvent2);
			}
		}

		public static event EventHandler<RoutineChangedEventArgs> OnRoutineChanged
		{
			[CompilerGenerated]
			add
			{
				EventHandler<RoutineChangedEventArgs> eventHandler = eventHandler_0;
				EventHandler<RoutineChangedEventArgs> eventHandler2;
				do
				{
					eventHandler2 = eventHandler;
					EventHandler<RoutineChangedEventArgs> value2 = (EventHandler<RoutineChangedEventArgs>)Delegate.Combine(eventHandler2, value);
					eventHandler = Interlocked.CompareExchange(ref eventHandler_0, value2, eventHandler2);
				}
				while ((object)eventHandler != eventHandler2);
			}
			[CompilerGenerated]
			remove
			{
				EventHandler<RoutineChangedEventArgs> eventHandler = eventHandler_0;
				EventHandler<RoutineChangedEventArgs> eventHandler2;
				do
				{
					eventHandler2 = eventHandler;
					EventHandler<RoutineChangedEventArgs> value2 = (EventHandler<RoutineChangedEventArgs>)Delegate.Remove(eventHandler2, value);
					eventHandler = Interlocked.CompareExchange(ref eventHandler_0, value2, eventHandler2);
				}
				while ((object)eventHandler != eventHandler2);
			}
		}

		public static bool Load()
		{
			try
			{
				string routinesPath = RoutinesPath;
				if (Routines != null)
				{
					ilog_0.ErrorFormat("[Load] This function can only be called once.");
					return false;
				}
				if (!Directory.Exists(routinesPath))
				{
					Directory.CreateDirectory(routinesPath);
				}
				AssemblyLoader<IRoutine> assemblyLoader = new AssemblyLoader<IRoutine>(routinesPath, detectFileChanges: false);
				Routines = new List<IRoutine>();
				foreach (IRoutine item in assemblyLoader.Instances.AsReadOnly())
				{
					try
					{
						Utility.smethod_0(item);
						item.Initialize();
						Routines.Add(item);
					}
					catch (Exception exception)
					{
						ilog_0.Debug("[Load] Exception thrown when initializing " + item.Name + ". Routine will not be loaded.", exception);
						Utility.smethod_1(item);
						item.Deinitialize();
					}
				}
				return true;
			}
			catch (Exception arg)
			{
				ilog_0.ErrorFormat("[Load] An exception occurred: {0}.", arg);
			}
			return false;
		}

		public static void Start()
		{
			Start(CurrentRoutine);
		}

		public static void Start(IRoutine routine)
		{
			smethod_0(routine, routineEvent_0);
			try
			{
				routine.Start();
			}
			catch (Exception exception)
			{
				ilog_0.Error("Exception during routine Start.", exception);
			}
			smethod_0(routine, routineEvent_1);
		}

		public static void Tick()
		{
			Tick(CurrentRoutine);
		}

		public static void Tick(IRoutine routine)
		{
			smethod_0(routine, routineEvent_2);
			try
			{
				routine.Tick();
			}
			catch (Exception exception)
			{
				ilog_0.Error("Exception during routine Tick.", exception);
			}
			smethod_0(routine, routineEvent_3);
		}

		public static void Stop()
		{
			Stop(CurrentRoutine);
		}

		public static void Stop(IRoutine routine)
		{
			smethod_0(routine, routineEvent_4);
			try
			{
				routine.Stop();
			}
			catch (Exception exception)
			{
				ilog_0.Error("Exception during routine Stop.", exception);
			}
			smethod_0(routine, routineEvent_5);
		}

		private static void smethod_0(IRoutine iroutine_1, RoutineEvent routineEvent_6)
		{
			if (routineEvent_6 != null)
			{
				try
				{
					routineEvent_6(iroutine_1);
				}
				catch (Exception exception)
				{
					ilog_0.Error("[Invoke] Error during execution:", exception);
				}
			}
		}

		public static void Deinitialize()
		{
			if (Routines == null)
			{
				return;
			}
			foreach (IRoutine routine in Routines)
			{
				try
				{
					routine.Deinitialize();
				}
				catch (Exception arg)
				{
					ilog_0.ErrorFormat("[RoutineManager] An exception occurred in {0}'s Deinitialize function. {1}", routine.Name, arg);
				}
			}
			Routines.Clear();
		}
	}
}
